package com.cdty.chess.service.impl;

import com.cdty.chess.model.MessageQueue;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.UUID;

@Service
public class MessageServiceImpl {

    @Autowired
    private NamedParameterJdbcTemplate template;

    /*@Autowired
    private MyWebSocketHandler webSocketHandler;*/

    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 批量保存消息到数据库
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void saveMessages(List<MessageQueue> messages) {
        if (messages == null || messages.isEmpty()) {
            return;
        }

        // 准备批量参数
        MapSqlParameterSource[] batchParams = new MapSqlParameterSource[messages.size()];

        for (int i = 0; i < messages.size(); i++) {
            MessageQueue batch = messages.get(i);
            try {
                String contentJson = objectMapper.writeValueAsString(batch.getContent());

                batchParams[i] = new MapSqlParameterSource()
                        .addValue("id", UUID.randomUUID().toString())
                        .addValue("eventType", batch.getEvent_type())
                        .addValue("content", contentJson)
                        .addValue("targetUid", batch.getTarget_uid())
                        .addValue("isBroadcast", batch.getIs_broadcast())
                        .addValue("isMasterOnly", batch.getIs_master_only())
                        .addValue("status", "PENDING");
            } catch (JsonProcessingException e) {
                throw new RuntimeException("Failed to serialize message content", e);
            }
        }

        // 批量插入
        String sql = """
                INSERT INTO message_queue 
                (id, event_type, content, target_uid, is_broadcast, is_master_only, status)
                VALUES 
                (:id, :eventType, :content, :targetUid, :isBroadcast, :isMasterOnly, :status)
                """;

        template.batchUpdate(sql, batchParams);
    }

    /**
     * 发送消息并更新状态
     */
    @Transactional
    public boolean sendMessage(MessageQueue message) {
        /*try {
            boolean sent = false;

            if (message.isBroadcast()) {
                webSocketHandler.broadcastAll(message.getContent());
                sent = true;
            } else if (message.isMasterOnly()) {
                webSocketHandler.broadToMaster(message.getContent());
                sent = true;
            } else if (message.getTargetUid() != null) {
                webSocketHandler.broadToUid(message.getTargetUid(), message.getContent());
                sent = true;
            }

            if (sent) {
                updateMessageStatus(message.getId(), "SENT");
                return true;
            }

            return false;
        } catch (Exception e) {
            updateMessageStatus(message.getId(), "FAILED");
            incrementRetryCount(message.getId());
            return false;
        }*/
        return false;
    }

    /**
     * 确认消息接收
     */
    @Transactional
    public void confirmMessage(String messageId) {
        updateMessageStatus(messageId, "CONFIRMED");
    }

    /**
     * 定时重发失败的消息
     */
    @Scheduled(fixedDelay = 30000) // 每30秒检查一次
    public void retryFailedMessages() {
        String sql = """
                SELECT * FROM message_queue 
                WHERE status IN ('PENDING', 'FAILED') 
                AND retry_count < max_retry
                ORDER BY create_time ASC
                LIMIT 100
                """;

        List<MessageQueue> messages = template.query(sql,
                new MapSqlParameterSource(),
                new BeanPropertyRowMapper<>(MessageQueue.class));

        for (MessageQueue message : messages) {
            sendMessage(message);
        }
    }

    private void updateMessageStatus(String messageId, String status) {
        String sql = "UPDATE message_queue SET status = :status WHERE id = :id";
        template.update(sql, new MapSqlParameterSource()
                .addValue("id", messageId)
                .addValue("status", status));
    }

    private void incrementRetryCount(String messageId) {
        String sql = "UPDATE message_queue SET retry_count = retry_count + 1 WHERE id = :id";
        template.update(sql, new MapSqlParameterSource("id", messageId));
    }
}